package org.spolo.android.support.nodetree;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.spolo.android.app.bean.ActionParameter;
import org.spolo.android.app.bean.GestureType;
import org.spolo.android.support.enventmanager.EventHandlerInterface;
import org.spolo.android.support.enventmanager.EventQueue;
import org.spolo.android.support.enventmanager.EventQueueInterface;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.View;

/**
 * @author chenzhongming
 * @date 2012-5-25
 */
public class Vcanvas implements Comparable<Vcanvas> {

	protected float startX = 0;
	protected float startY = 0;
	protected float width = 0;
	protected float height = 0;
	protected View view;
	protected Paint paint;
	protected Context context;
	protected Vcanvas m_parent;
	protected RectF dirty_rect;
	protected ArrayList<Vcanvas> m_children;
	/**
	 * 移动代号
	 */
	public static final int MOVE = 1;
	/**
	 * 旋转代号
	 */
	public static final int ROTATE = 2;
	/**
	 * 缩放代号
	 */
	public static final int SCALE = 3;
	/**
	 * 透明代号
	 */
	public static final int ALPHA = 4;
	/**
	 * 只负责平移变换
	 */
	protected Matrix m_PointMatrix = new Matrix();
	/**
	 * 只负责旋转变换
	 */
	protected Matrix r_PointMatrix = new Matrix();
	/**
	 * 只负责缩放变换
	 */
	protected Matrix s_PointMatrix = new Matrix();
	protected EventQueue m_eventQueue = new EventQueue();

	// 层叠属性
	public int zIndex = 0;
	private Matrix tmp;
	/**
	 * 该标记在切换topic时判断是否从topic中的list中移除
	 */
	public boolean isFixed = true;

	// 控制元素是否显示
	private boolean isVisible = true;

	public Vcanvas() {
		this.dirty_rect = new RectF();
		this.m_children = new ArrayList<Vcanvas>();
		this.paint = new Paint();
		this.paint.setColor(Color.WHITE);
	}

	/**
	 * 向当前元素添加一个子元素
	 * 
	 * @param vcanvas
	 */
	public void addChild(Vcanvas vcanvas) {
		this.getM_children().add(vcanvas);
		vcanvas.setVParent(this);
		// 父子相对坐标的维护
		vcanvas.startX += vcanvas.getVParent().startX;
		vcanvas.startY += vcanvas.getVParent().startY;

		vcanvas.AddSelfAllDirty();
	}

	/**
	 * 每个Vcanvas的子类重写此方法，实现自己的绘制内容
	 * 
	 * @param canvas
	 *            利用此对象提供诸多的绘制方法，来完成绘制内容
	 */
	protected void drawSelfImplement(Canvas canvas) {
	}

	protected void drawSelf(Canvas canvas, float px, float py) {
		// 获取当前canvas对象的Matrix 父类矩阵乘以当前元素的矩阵实现子元素跟随父元素同步变换.
		// 将变化后的矩阵设为canvas对象的当前矩阵，并将变化后的矩阵恢复
		// if (!Stage.getInstance().DirtyContainRect(dirty_rect)) {
		// return;
		// } else {
		canvas.save();

		// if (!this.m_PointMatrix.isIdentity()) {
		Matrix canvasMatrix = canvas.getMatrix();
		Matrix sum = new Matrix();
		// 最终所有变换矩阵的积再相乘
		sum.preConcat(new Matrix(m_PointMatrix));
		sum.preConcat(new Matrix(r_PointMatrix));
		sum.preConcat(new Matrix(s_PointMatrix));

		tmp = new Matrix(sum);
		tmp.postConcat(canvasMatrix);
		canvas.setMatrix(tmp);
		// }
		// 调用子类的实现
		drawSelfImplement(canvas);
		Collections.sort(this.getM_children());
		// 遍历所有子类
		for (Vcanvas v : this.getM_children()) {
			v.drawSelf(canvas, px, py);
		}
		// 整棵场景树绘完之后让canvas的矩阵恢复初始
		canvas.setMatrix(canvasMatrix);
		// canvas.restore();
		// }
	}

	/**
	 * 消息的处理
	 * 
	 * @param type
	 *            事件类型
	 * @param me
	 *            事件参数对象
	 * @return
	 */
	protected boolean handleEvent(int type, Object me) {
		// 强制转型为ActionParameter并取出参数中的事件对象集合
		// 然后将第一个事件对象作为判断依据
		ActionParameter ap = (ActionParameter) me;
		MotionEvent e1 = ap.getEvents().get(0);
		if (type < 10) {
			if (isChecked(e1.getX(), e1.getY())) {

				Map<Integer, List<EventHandlerInterface>> map = this
						.GetEventQueue().getEventMap();
				if (map.containsKey(type)) {
					ap.setVcanvas(this);
					this.GetEventQueue().publish(type, me);
					return true;
				}
			}
		} else {
			this.GetEventQueue().publish(type, me);
			this.GetEventQueue().removeListner(GestureType.JUMPTOPIC);
		}
		return false;
	}

	/**
	 * 事件到来之后先看自己是否该处理，并且将事件向子元素传递
	 * 
	 * @brief 深度优先遍历。
	 * @param type
	 *            事件类型
	 * @param me
	 *            事件参数对象
	 * @return
	 */
	protected boolean recuriHandleEvent(int type, Object me) {
		for (int i = this.getM_children().size() - 1; i >= 0; i--) {
			Vcanvas v = this.getM_children().get(i);
			if (v.recuriHandleEvent(type, me))
				return true;
		}
		return handleEvent(type, me);
	}

	/**
	 * 平移
	 * 
	 * @param dx
	 *            △X
	 * @param dy
	 *            △Y
	 */
	public void Move(float dx, float dy) {
		// AddSelfAllDirty();
		this.m_PointMatrix.preTranslate(dx, dy);
		changeRect();
		AddSelfAllDirty();
	}

	/**
	 * 绕元素中心旋转
	 * 
	 * @param d
	 *            角度
	 */

	public void Rotate(float d) {
		// AddSelfAllDirty();
		float[] center = getCenter();
		this.r_PointMatrix.preRotate(d, center[0], center[1]);
		changeRect();
		AddSelfAllDirty();
	}

	/**
	 * 使此元素以指定的角度,在指定的坐标点旋转
	 * 
	 * @param d
	 *            旋转的角度
	 * @param x
	 *            指定坐标点的x值
	 * @param y
	 *            指定坐标点的 值
	 */
	public void Rotate(float d, float x, float y) {
		// AddSelfAllDirty();
		this.r_PointMatrix.preRotate(d, x, y);
		changeRect();
		AddSelfAllDirty();
	}

	/**
	 * 沿x,y轴缩放
	 * 
	 * @param x
	 *            X轴向缩放的倍数
	 * @param y
	 *            Y轴向缩放的倍数
	 */
	public void Scale(float x, float y) {
		float[] center = getCenter();
		// AddSelfAllDirty();
		this.width = this.width * x;
		this.s_PointMatrix.preScale(x, y, center[0], center[1]);
		changeRect();
		AddSelfAllDirty();
	}

	/**
	 * @param a
	 */
	public void setAlpha(int a) {
		this.paint.setAlpha(a);
		AddSelfAllDirty();
	}

	/**
	 * 删除一个子元素
	 * 
	 * @param v
	 */
	public void removeChild(Vcanvas v) {
		this.getM_children().remove(v);
		v.AddSelfAllDirty();
	}

	/**
	 * 检查所操作的是否为自己
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	protected boolean isChecked(float x, float y) {
		RectF rect = this.getRect();
		if (rect.contains(x, y))
			return true;
		return false;
	}

	/**
	 * 获取此元素中心位置坐标
	 * 
	 * @return float[] 返回当前元素的中心点坐标 x = float[0] y = float[1]
	 */
	public float[] getCenter() {
		float[] result = new float[2];
		// 获取中心点
		result[0] = (this.startX + (this.width) / 2);
		result[1] = (this.startY + (this.height) / 2);
		return result;
	}

	protected void AddSelfAllDirty() {
		Stage.getInstance().AddDirtyRect(dirty_rect);
	}

	/**
	 * 在图形变换的时候让包裹此图形的脏区同步跟着变化
	 */
	private void changeRect() {
		float[] point_left_top = new float[] { startX, startY };
		float[] point_left_bottom = new float[] { startX, startY + height };
		float[] point_reight_top = new float[] { startX + width, startY };
		float[] point_reight_bottom = new float[] { startX + width,
				startY + height };
		this.tmp.mapPoints(point_left_top);
		this.tmp.mapPoints(point_left_bottom);
		this.tmp.mapPoints(point_reight_top);
		this.tmp.mapPoints(point_reight_bottom);

		float[] x = new float[] { point_left_top[0], point_left_bottom[0],
				point_reight_top[0], point_reight_bottom[0] };
		float[] y = new float[] { point_left_top[1], point_left_bottom[1],
				point_reight_top[1], point_reight_bottom[1] };
		float min_x = x[0];
		float max_x = x[0];
		for (int i = 0; i < x.length; i++) {
			if (x[i] < min_x) {
				min_x = x[i];
			}
			if (x[i] > max_x) {

				max_x = x[i];
			}
		}
		float min_y = y[0];
		float max_y = y[0];
		for (int i = 0; i < x.length; i++) {
			if (x[i] < min_y) {
				min_y = x[i];
			}
			if (x[i] > max_y) {

				max_y = x[i];
			}
		}
		this.dirty_rect.set(min_x, min_y, max_x, max_y);

	}

	/**
	 * @param type
	 *            图形变换的类型 例如Vcanvas.MOVE
	 * @param x
	 *            此参数根据前面传入的类型决定其作用,如果是MOVE就是在X轴向移动的位移,
	 *            如果是ROTATE就是旋转的角度如果是SCALE就是在X轴向缩放的系数
	 * @param y
	 *            此参数根据前面传入的类型决定其作用,如果是MOVE就是在Y轴向移动的位移,
	 *            如果是ROTATE或者ALPHA无意义可设可不设如果是SCALE就是在Y轴向缩放的系数
	 * 
	 */
	public void setValues(int type, float x, float y) {
		switch (type) {
		case MOVE:
			this.Move(x, y);
			break;
		case ROTATE:
			this.Rotate(x);
			break;
		case SCALE:
			this.Scale(x, y);
			break;
		case ALPHA:
			this.setAlpha((int) x);
			break;
		}
	}

	/**
	 * 设置脏区
	 * 
	 * @param left
	 *            矩形左上点坐标x值
	 * @param top
	 *            矩形左上点坐标y值
	 * @param width
	 *            矩形的宽度
	 * @param height
	 *            矩形的高度
	 * 
	 */
	protected void setDirtyRect(float left, float top, float width, float height) {
		this.startX = left;
		this.startY = top;
		this.width = width;
		this.height = height;
		dirty_rect.set(left, top, width + left, top + height);
	}

	/**
	 * 获取当前元素的父元素
	 * 
	 * @return Vcanvas
	 */
	public Vcanvas getVParent() {
		return m_parent;
	}

	private void setVParent(Vcanvas parent) {
		this.m_parent = parent;
	}

	/**
	 * 得到当前元素所有的子元素
	 * 
	 * @return ArrayList<Vcanvas>
	 * 
	 */
	public ArrayList<Vcanvas> getM_children() {
		return this.m_children;
	}

	public void setM_children(ArrayList<Vcanvas> m_children) {
		this.m_children = m_children;
	}

	/**
	 * 获取当前元素的Patin对象，此对象可以设置此元素的颜色，透明，等等
	 * 
	 * @return Paint
	 */
	public Paint getPaint() {
		return this.paint;
	}

	public RectF getRect() {
		return dirty_rect;
	}

	public EventQueueInterface GetEventQueue() {
		return m_eventQueue;
	}

	@Override
	public int compareTo(Vcanvas another) {
		if (this.zIndex > another.zIndex) {
			return 1;
		} else if (this.zIndex == another.zIndex) {
			return 0;
		}
		return -1;
	}

	/**
	 * 判断当前元素显示状态
	 * 
	 * @return
	 */
	public boolean isVisible() {
		return isVisible;
	}

	/**
	 * 设置元素的显示状态 true为显示,false为隐藏(目前实际上是做的add,与del的操作)
	 * 
	 * @param visible
	 */
	public void setVisible(boolean visible) {
		this.isVisible = visible;
	}

}
